package cn.fcj.f20240328.fsocket.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.HashMap;
import java.util.Map;

import cn.fcj.f20240328.fsocket.base.FBaseNIOSocket;
import cn.fcj.f20240328.fsocket.base.ISocketEventHandler;

/**
 * @项目名称:Fsocket
 * @功能描述:socket服务器端实现
 * @开发　者:mochhk
 * @邮　　箱:mochhk@163.com
 * @CreateDate:2024/4/5 13:27
 */
public class FNIOSocketServer extends FBaseNIOSocket<ServerSocketChannel> {
    public SelectorsManager selectorsManager;
    public static Map<String,SelectionKey> clients;//保存所有socket连接，发消息时选择对应的ip发送

    public FNIOSocketServer(){
        clients=new HashMap<>();
        selectorsManager=new SelectorsManager();
    }
    public SelectionKey getClientKey(String ip){
       return clients.get(ip);
    }

    @Override
    public void initSocket() throws IOException {
        System.out.println("----------服务器正在启动......");
        //1)开启多路复用器
        mSelector = Selector.open();
        //2) 开启服务通道
        mChannel = ServerSocketChannel.open();
        //3)设置为非阻塞
        mChannel.configureBlocking(false);
        //4)绑定端口
        mChannel.bind(new InetSocketAddress(port));
        //5)注册,标记服务通标状态
        mChannel.register(mSelector, SelectionKey.OP_ACCEPT);
        System.out.println("-------------服务器启动完毕----------------");
    }
    @Override
    public void connectionHandler(SelectionKey key) throws IOException {
        //判断接受请求连接
        SelectionKey newkey=null;
        if (key.isAcceptable()) {
            System.out.println("-------------服务器运行中----有新连接------------");
            newkey=selectorsManager.acceptAndRegister(key,clients);
            super.connectionHandler(newkey);
        }
    }

    @Override
    public void channelEvenHandler(SelectionKey key) throws CancelledKeyException, IOException {

    }

    @Override
    public void exceptionHandler(Exception e, ErrorCode errorCode, SelectionKey key) {
        super.exceptionHandler(e, errorCode, key);
        if(key!=null){
            key.cancel();
        }
    }

    @Override
    public FBaseNIOSocket setSocketEventHandler(ISocketEventHandler socketEventHandler) {
        selectorsManager.setSocketEventHandler(socketEventHandler);
        return super.setSocketEventHandler(socketEventHandler);
    }

    @Override
    public void stopSocket() {
        clients.clear();
        selectorsManager.stopWorkPool();
        super.stopSocket();
    }
}
